Skip to main content

Attribut: pack_mode

Das Pragma legt fest, wie eine Datenstruktur während der Allozierung gepackt wird. Das Attribut muss oberhalb der Datenstruktur eingefügt werden und wirkt sich auf das Packen der gesamten Struktur aus.

Syntax:

{attribute 'pack_mode' := ' <pack mode value> '}

Einfügeort: Oberhalb der Deklaration der Datenstruktur

Tabelle 25. Mögliche Werte für <pack mode value>

<pack mode value>

Assoziierte Packungsart

Beschreibung

0

aligned

Es liegen alle Variablen auf Byte-Adressen; es treten keine Speicherlücken auf.

1

1-byte-aligned

2

2-byte-aligned

. Es liegen
  • 1 Byte-Variablen auf Byte-Adressen

  • 2 Byte-Variablen auf durch 2-teilbare Adressen. Es entsteht maximal eine Lücke von 1 Byte

  • 4 Byte-Variablen auf durch 2-teilbare Adressen. Es entsteht maximal eine Lücke von 1 Byte

  • 8 Byte-Variablen auf durch 2-teilbare Adressen. Es entsteht maximal eine Lücke von 1 Byte

  • Strings immer an Byte-Adressen. Es entsteht keine Lücke.

4

4-byte-aligned

. Es liegen
  • 1 Byte-Variablen auf Byte-Adressen

  • 2 Byte-Variablen auf durch 2-teilbare Adressen. Es entsteht maximal eine Lücke von 1 Byte

  • 4 Byte-Variablen auf durch 4-teilbare Adressen. Es entsteht maximal eine Lücke von 3 Byte

  • 8 Byte-Variablen auf durch 4-teilbare Adressen. Es entsteht maximal eine Lücke von 3 Byte

  • Strings immer an Byte-Adressen. Es entsteht keine Lücke.

8

8-byte-aligned

. Es liegen
  • 1 Byte-Variablen auf Byte-Adressen

  • 2 Byte-Variablen auf durch 2-teilbare Adressen. Es entsteht maximal eine Lücke von 1 Byte

  • 4 Byte-Variablen auf durch 4-teilbare Adressen. Es entsteht maximal eine Lücke von 3 Byte

  • 8 Byte-Variablen auf durch 8-teilbare Adressen. Es entsteht maximal eine Lücke von 7 Byte

  • Strings immer an Byte-Adressen. Es entsteht keine Lücke.



Tipp

Abhängig vom Aufbau der Struktur kann es vorkommen, dass es keinen Unterschied in der Speicheraufteilung zwischen den einzelnen Modi gibt. Beispielsweise kann die Speicherverteilung einer Struktur mit dem Pragma {attribute 'pack mode' := '4'} der von {attribute 'pack mode' := '8'} entsprechen.

Tipp

Arrays von Strukturen

Werden die Strukturen in Arrays zusammengefasst, dann werden am Ende der Struktur Bytes eingefügt, damit die nächste Struktur wieder aligned ist.

Wichtig

Wenn in der Symbolkonfiguration die Option Kompatibilitätslayout aktiviert wird und gleichzeitig das Attribut 'pack_mode' im Code verwendet wird, können Probleme wegen unabsichtlich falscher Speicherausrichtung auftreten.

Beispiel 1

{attribute 'pack_mode' := '1'}

TYPE myStruct:
STRUCT
  Enable: BOOL;
  Counter: INT;
  MaxSize: BOOL;
  MaxSizeReached: BOOL;
  END_STRUCT
END_TYPE

Der Speicherbereich für eine Variable vom Datentyp myStruct wird „aligned“ alloziert: Ist die Speicheradresse ihrer Komponente Enable beispielsweise 0x0100, dann folgt die Komponente Counter an der Adresse 0x0101, MaxSize an Adresse 0x0103 und MaxSizeReached an Adresse 0x0104. Mit 'pack_mode':=2 läge Counter bei 0x0102, MaxSize bei 0x0104 und MaxSizeReached bei 0x0105.

Beispiel 2

STRUCT
  Var1 : BOOL  := 16#01;
  Var2 : BYTE  := 16#11;
  Var3 : WORD  := 16#22;
  Var4 : BYTE  := 16#44;
  Var5 : DWORD := 16#88776655;
  Var6 : BYTE  := 16#99;
  Var7 : BYTE  := 16#AA;
  Var8 : DWORD := 16#AA;
END_TYPE

pack_mode = 8

pack_mode = 0

pack_mode = 1

pack_mode = 2

pack_mode = 4

Variable

Wert

Variable

Wert

Variable

Wert

Variable

Wert

Variable

Wert

0

Var1

01

Var1

01

Var1

01

Var1

01

Var1

01

1

Var2

11

Var2

11

Var2

11

Var2

11

Var2

11

2

Var3

22

Var3

22

Var3

22

Var3

22

Var3

22

3

00

00

00

00

00

4

Var4

44

Var4

44

Var4

44

Var4

44

Var4

44

5

Var5

55

Var5

55

6

66

66

Var5

55

7

77

77

66

8

Var5

55

88

88

77

Var5

55

9

66

Var6

99

Var6

99

88

66

10

77

Var7

AA

Var7

AA

Var6

99

77

11

88

Var8

AA

Var8

AA

Var7

AA

88

12

Var6

99

00

00

Var8

AA

Var6

99

13

Var7

AA

00

00

00

Var7

AA

14

00

00

00

15

00

16

Var8

AA

Var8

AA

17

00

00

18

00

00

19

00

00

20

21

22

23

24

25

26

27

28

29

30

31

Beispiel 3

STRUCT
    Var1 : BYTE  := 16#01;
    Var2 : LWORD := 16#11;
    Var3 : BYTE  := 16#22;
    Var4 : BYTE  := 16#44;
    Var5 : DWORD := 16#88776655;
    Var6 : BYTE  := 16#99;
    Var7 : BYTE  := 16#AA;
    Var8 : WORD  := 16#AA;
END_TYPE

pack_mode = 8

pack_mode = 0

pack_mode = 1

pack_mode = 2

pack_mode = 4

Variable

Wert

Variable

Wert

Variable

Wert

Variable

Wert

Variable

Wert

0

Var1

01

Var1

01

Var1

01

Var1

01

Var1

01

1

Var2

11

Var2

11

2

00

00

Var2

11

3

00

00

00

4

00

00

00

Var2

11

5

00

00

00

00

6

00

00

00

00

7

00

00

00

00

8

Var2

11

00

00

00

00

9

00

Var3

22

Var3

22

00

00

10

00

Var4

44

Var4

44

Var3

22

00

11

00

Var5

55

Var5

55

Var4

44

00

12

00

66

66

Var5

55

Var3

22

13

00

77

77

66

Var4

44

14

00

88

88

77

15

00

Var6

99

Var6

99

88

16

Var3

22

Var7

AA

Var7

AA

Var6

99

Var5

55

17

Var4

44

Var8

AA

Var8

AA

Var7

AA

66

18

00

00

Var8

AA

77

19

00

88

20

Var5

55

Var6

99

21

66

Var7

AA

22

77

Var8

AA

23

88

00

24

Var6

99

25

Var7

AA

26

Var8

AA

27

00

28

29

30

31

Verhalten ohne 'pack-mode'

Wenn 'pack-mode' nicht verwendet wird, dann verwendet der Compiler typischerweise pack-mode 4 oder 8, abhängig von der Gerätebeschreibung. In jedem Fall wird ein für den Prozessor besonders vorteilhafter pack-mode verwendet, so dass Speicherzugriffe besonders effizient durchgeführt werden können. Dies wird auch natürliches Alignment genannt, oder eine natürliche Ausrichtung der Daten.

Negative Auswirkungen bei Anwendung von 'pack-mode'

Durch die Verwendung des Attributs 'pack_mode' kann es zu nicht ausgerichteten Speicherzugriffen kommen. Das bedeutet beispielsweise, dass ein Datentyp der Größe 4 Byte dann auf einer Adresse liegt, die nicht durch 4 teilbar ist. Normalerweise kann auf einem 32-Bit-System ein 32 Bit großer Datentyp mit einem einzigen Speicherzugriff gelesen und geschrieben werden. Auf manchen Plattformen, wie beispielsweise auf ARM-Plattformen, ist das jedoch nur möglich, wenn dieser Wert im Speicher ausgerichtet ist. Auf anderen Plattformen kann es sein, dass der Zugriff zwar möglich ist, aber deutlich langsamer ausgeführt wird.

{attribute 'pack_mode':=1}

TYPE DUT
STRUCT
    by1 : BYTE;
    dw1 : DWORD;
END_STRUCT
END_TYPE

Auf einer ARM-Plattform kann der Wert dw1 nicht mit einem einzigen Zugriff gelesen werden. Bei dem Versuch auf dieses Element direkt zuzugreifen, wird der ARM-Prozessor eine Exception auslösen.

Annahme: Folgender lesender Zugriff wird durchgeführt: dwTest := dut1.dw1;

Für diesen Zugriff auf das DWORD dw1 werden 4 Speicherzugriffe benötigt, da jedes Byte einzeln eingelesen, geshiftet und verodert wird. Der Ablauf ist in etwa der Gleiche, wie wenn in dem folgenden Beispiel aus einem Array von 4 Bytes ein DWORD generiert wird:

dwHelp := bytes[0];
dwResult := dwHelp;
dwHelp := bytes[1];
dwHelp := SHL(dwHelp, 8);
dwResult := dwResult OR dwHelp;
dwHelp := bytes[2];
dwHelp := SHL(dwHelp, 16);
dwResult := dwResult OR dwHelp;
dwHelp := bytes[3];
dwHelp := SHL(dwHelp, 24);
dwResult := dwResult OR dwHelp;

Es ist offensichtlich, dass ein solcher Zugriff deutlich langsamer ist als ein Zugriff auf ein DWORD, das passend im Speicher ausgerichtet ist.

pdw := ADR(dut1.dw1);
dwTest := pdw^;

Den Zugriff des Beispiels wird der Compiler jedoch nicht generieren, wenn über einen Pointer auf eine solche Komponente zugegriffen wird. Das bedeutet, dass der folgende Code auf einer ARM-Plattform zu einer Exception führt.

pdw := ADR(dut1.dw1);
dwTest := pdw^;

Aus Performance-Gründen sollte es daher vermieden werden, mit Strukturen zu arbeiten, die nicht natürlich ausgerichtet sind.

Eine gepackte Struktur darf keine ungepackte Struktur enthalten.